package com.klikmee.sms.chat.web.senders;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.klikmee.sms.cef.services.Service;
import com.klikmee.sms.services.chat.model.Question;

/**
 * ***************************************************************************** ***
 * <p>
 * This impl of {@link MessageSender} uses 2 service instances to send messages. Used to simulate bulk messaging like following:
 * </p>
 * <p>
 * First chunk of the message is send via the first service and charged to the user. Other parts (if any) are send via second service impl and are free of charge for the user.
 * </p>
 * 
 * @author makcro
 ********************************************************************************* 
 * 
 */
public class DualServiceMessageSenderImpl extends AbstractMessageSender {

	/**
	 * Logger instance
	 */
	private Logger logger = Logger.getLogger(DualServiceMessageSenderImpl.class);

	/**
	 * Charging service settings
	 */
	private Long chargingId = null;
	private Long chargingServiceId = null;
	/**
	 * Bulk service settings
	 */
	private Long bulkChargingId = null;
	private Long bulkServiceId = null;

	/**
	 * Sends charging message by splitting it on 160 and 153 character chunks.
	 * 
	 * @param messageText
	 *            message to send
	 * @param coreReferenceId
	 *            reference id of the initial end user's request.
	 * @return number of parts sent
	 */
	@Override
	public Long sendMessage(String messageText, Long coreReferenceId, Object data) {

		// expect Question as additional data
		Question question = (Question) data;

		// check if this is a long message and split it into smaller chunks
		List<String> messageParts = splitMessage(messageText);

		// send the firs part via charging service
		String firstPart = messageParts.get(0);
		Long chargedCoreRefId = coreAdapter.sendMessage(this.chargingId, this.chargingServiceId, Service.SERVICE_FLAG_SEMANTIC_OK, coreReferenceId, firstPart);
		persistAnswer(question, messageText, chargedCoreRefId, true);
		
		logger.info(MessageFormat.format("Sent charged part with service [{0}] and charging [{1}]", this.chargingServiceId, this.chargingId));
		
		// if there are others, send them via bulk service
		if (messageParts.size() > 1) {
			for (int i = 1; i < messageParts.size(); i++) {
				String currentPart = messageParts.get(i);
				Long currentPartCoreRefId = coreAdapter.sendMessage(this.bulkChargingId, this.bulkServiceId, Service.SERVICE_FLAG_SEMANTIC_OK, coreReferenceId, currentPart);
				persistAnswer(question, currentPart, currentPartCoreRefId, false);
			
				logger.info(MessageFormat.format("Sent bulk part [{0}] with service id [{1}] and charging id [{2}]", i, this.bulkServiceId, this.bulkChargingId));
			}
		}

		return (long) messageParts.size();
	}

	/**
	 * Splits message into long messge chunks
	 * 
	 * @param longMessage
	 *            complete message text
	 * @return list of message chunks
	 */
	private List<String> splitMessage(String longMessage) {
		ArrayList<String> parts = new ArrayList<String>();
		int partSize = 153;
		// characters total
		int messageLength = longMessage.length();
		// index of last split
		int delimiter = 0;
		int rest = messageLength - delimiter;
		// if rest of the message is bigger then part size, then split the rest
		// and move delimiter
		while (rest > partSize) {
			String part = longMessage.substring(delimiter, delimiter + partSize);
			parts.add(part);
			// decrement part size to fit other segments
			partSize = 153;
			delimiter += partSize;
			rest = messageLength - delimiter;
		}
		// if the rest is bigger then 0 then add it as final part
		if (rest > 0) {
			String finalPart = longMessage.substring(delimiter);
			parts.add(finalPart);
		}

		return parts;
	}

	public void setChargingId(Long chargingId) {
		this.chargingId = chargingId;
	}

	public void setChargingServiceId(Long chargingServiceId) {
		this.chargingServiceId = chargingServiceId;
	}

	public void setBulkChargingId(Long bulkChargingId) {
		this.bulkChargingId = bulkChargingId;
	}

	public void setBulkServiceId(Long bulkServiceId) {
		this.bulkServiceId = bulkServiceId;
	}

}
